﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Config;
using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Events;

namespace Microsoft.Samples.Office.UnifiedCommunications.Gadget
{
    public partial class Fav5Config : Page
    {
        Fav5ObservableCollection _fav5 = new Fav5ObservableCollection(); // Current Fav 5
        private Fav5DTO _fav5Contact; // Individual Fav 5 contact

        public Fav5Config()
        {
            InitializeComponent();
            
            this.Unloaded += new RoutedEventHandler(Fav5Config_Unloaded);
            this.MouseDown += new MouseButtonEventHandler(Fav5Config_MouseDown);
            
            this.btnHelp.MouseEnter += new MouseEventHandler(btnHelp_MouseEnter);
            this.btnHelp.MouseLeave += new MouseEventHandler(btnHelp_MouseLeave);

            GadgetEventManager.Instance.MismatchedSipEvent += new EventHandler(Instance_MismatchedSipEvent);
            GadgetEventManager.Instance.Fav5ContactDetailsConfirmedEvent += new EventHandler(Instance_Fav5ContactDetailsConfirmedEvent);
            GadgetEventManager.Instance.Fav5ChangedEvent += new EventHandler(Instance_Fav5ChangedEvent);
        }

        #region Loading

        void BackDoubleAnimation_Completed(object sender, EventArgs e)
        {
            this.listFav5.ItemsSource = _fav5;
        }

        void RefreshFav5List()
        {
            _fav5 = new Fav5ObservableCollection();
            listFav5.ItemsSource = _fav5;
        }

        void Fav5Config_Unloaded(object sender, RoutedEventArgs e)
        {
            this.MouseDown -= new MouseButtonEventHandler(Fav5Config_MouseDown);

            GadgetEventManager.Instance.MismatchedSipEvent -= new EventHandler(Instance_MismatchedSipEvent);
            GadgetEventManager.Instance.Fav5ContactDetailsConfirmedEvent -= new EventHandler(Instance_Fav5ContactDetailsConfirmedEvent);
            GadgetEventManager.Instance.Fav5ChangedEvent -= new EventHandler(Instance_Fav5ChangedEvent);
        }

        #endregion

        #region Miscellaneous UI

        void Fav5Config_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.listFav5.UnselectAll();
        }

        void btnHelp_MouseLeave(object sender, MouseEventArgs e)
        {
            (base.FindResource("fadeOut") as Storyboard).Begin(this.tooltip);
        }

        void btnHelp_MouseEnter(object sender, MouseEventArgs e)
        {
            (base.FindResource("fadeIn") as Storyboard).Begin(this.tooltip);
        }

        private void btnApply_Click(object sender, RoutedEventArgs e)
        {
            this.listFav5.UnselectAll();
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            SettingsWindow.Instance.Close();
        }

        #endregion

        #region Fav5 CRUD

        void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            // When the user manually makes a Fav5 entry, need to account for whether or not
            //  there already was an entry in the slot. Grab the current ListItem into a 
            //  temporary object so that TextBox_LostFocus can use it.
            //
            _fav5Contact = (Fav5DTO)listFav5.SelectedItem;
        }

        void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            int slot = _fav5Contact.Slot;

            // Get the Fav5 list that is stored in the user's settings file
            FavoriteElementCollection currentFav5 = GadgetConfigurationManager.GetCurrentFav5List();
            // Get the Fav5 element at the particular slot
            FavoriteElement favElement = currentFav5.GetByOrderKey(slot);

            string oldContactId = default(string);
            string oldDisplayName = default(string);
            string newText = default(string); // whatever text is in the textbox that raised this event

            // User is modifying an existing contact
            //
            if (favElement != null)
            {
                oldContactId = favElement.ContactID;
                oldDisplayName = favElement.DisplayName;
            }

            // Which TextBox 
            string textBoxName = ((TextBox)sender).Name;

            if (textBoxName == "txtFav5ContactId") // the event was raised from the Contact Id textbox
            {
                newText = _fav5Contact.ContactID; // the text that was entered

                if (favElement == null && String.IsNullOrEmpty(newText))        // No change
                {
                    return; // Do nothing
                }
                else if (favElement == null && !String.IsNullOrEmpty(newText))  // Adding Fav5 Contact
                {
                    AddFav5(slot, newText);
                }
                else if (favElement != null && String.IsNullOrEmpty(newText))   // Deleting Fav5 Contact
                {
                    RemoveFav5(slot, oldDisplayName);
                }
                else if (favElement != null && !String.IsNullOrEmpty(newText))  // Modifying Fav5 Contact
                {
                    if (oldContactId.Equals(newText, StringComparison.OrdinalIgnoreCase))   // Edit mode but didn't make any changes 
                    {
                        return; // No change
                    }
                    else
                    {
                        // Remove the Fav5 contact in the current slot and replace it with the new one
                        RemoveFav5(slot, oldDisplayName);
                        AddFav5(slot, newText);
                    }
                }
            }
            else if (textBoxName == "txtFav5DisplayName")
            { 
                newText = _fav5Contact.DisplayName; // The text that was entered

                if (favElement == null) 
                    return; // No Fav5 contact to edit

                if (!oldDisplayName.Equals(newText, StringComparison.OrdinalIgnoreCase))
                {
                    ModifyFav5(slot, newText);
                }
            }
        }

        void Instance_Fav5ContactDetailsConfirmedEvent(object sender, EventArgs e)
        {
            Fav5ChangedEventArgs args = e as Fav5ChangedEventArgs;
            RefreshFav5List();

            ShowMessage(String.Format("Added {0} to your Fav 5.", args.DisplayName));
        }

        void Instance_MismatchedSipEvent(object sender, EventArgs e)
        {

            MismatchedSIPEventArgs args = e as MismatchedSIPEventArgs;

            ShowMessage(String.Concat("Could not recognize ", args.SMTPAddress, " as a valid contact or phone number."));

            _fav5 = new Fav5ObservableCollection();
            listFav5.ItemsSource = _fav5;
        }

        void Instance_Fav5ChangedEvent(object sender, EventArgs e)
        {
            RefreshFav5List();
        }

        void Object_Drop(object sender, DragEventArgs e)
        {
            ShowMessage(null);

            try
            {
                Label lblFav5 = sender as Label;
                string dropstring = (string)(e.Data.GetData(DataFormats.Text, true));
                lblFav5.Content = dropstring;

                Point location = Mouse.GetPosition(this);   // Get the mouse position
                VisualTreeHelper.HitTest(this, null,        // Hit test to find Fav5 slot
                    new HitTestResultCallback(HitTestCallBack),
                    new PointHitTestParameters(location));
                int slot = ((Fav5DTO) listFav5.SelectedItem).Slot; // Hit test sets listbox selected item

                AddFav5(slot, dropstring);
            }
            catch
            {
                ShowMessage(String.Concat("Could not add this to your Fav 5.", Environment.NewLine,
                    "Could not recognize the item as a Communicator Contact."));
            }
        }

        HitTestResultBehavior HitTestCallBack(HitTestResult result)
        {
            if (VisualTreeHelper.GetParent(result.VisualHit) is ListBoxItem)
            {
                ItemContainerGenerator generator = this.listFav5.ItemContainerGenerator;
                ListBoxItem fav5Item = (ListBoxItem)VisualTreeHelper.GetParent(result.VisualHit);
                int rowIndex = generator.IndexFromContainer(fav5Item);
                Fav5DTO fav5 = (Fav5DTO)listFav5.Items[rowIndex];
                listFav5.SelectedItem = fav5;
            }

            return HitTestResultBehavior.Continue;
        }

        void radioDefaultClickAction_Checked(object sender, RoutedEventArgs e)
        {
            // The GroupName of all three RadioButton is bound to the Fav5 Slot
            //

            int slot = Convert.ToInt32(((RadioButton)sender).GroupName);
            Fav5DTO contact = _fav5[slot - 1];

            if (String.IsNullOrEmpty(contact.ContactID) && String.IsNullOrEmpty(contact.DisplayName))
                return; // An empty slot ...

            // Check if the ClickAction has changed
            //  Remember that this event gets raised when the Fav5 were originally loaded
            //

            ClickAction clickAction = DefaultClickAction.FriendlyNameToEnum(((RadioButton)sender).Tag.ToString());

            if (clickAction != contact.DefaultClickAction)
            {
                GadgetConfigurationManager.ModifyFavorite5ClickAction(slot, clickAction.ToString());

                Fav5ChangedEventArgs args = new Fav5ChangedEventArgs
                {
                    Operation = Fav5Operation.Modify,
                    OrderKey = slot,
                    SIPUri = contact.ContactID,
                    DisplayName = contact.DisplayName,
                    Success = true
                };
                GadgetEventManager.Instance.OnFav5ChangedEvent(args);
            }
        }

        bool Fav5ContactAlreadyExists(string sipUri)
        {
            bool exists = false;

            FavoriteElementCollection curFav5 = GadgetConfigurationManager.GetCurrentFav5List();
            foreach (FavoriteElement fav in curFav5)
            {
                if (fav.ContactID == sipUri) // already in Fav5
                {
                    exists = true;
                    break;
                }
            }

            return exists;
        }

        void AddFav5(int orderKey, string sipUri)
        {
            ShowMessage(null);

            if (!Fav5ContactAlreadyExists(sipUri))
            {
                // Raise an event to the Gadget window
                //  The Gadget window will verify the contact and raise an event to notify this window.
                //
                Fav5ChangedEventArgs args = new Fav5ChangedEventArgs
                {
                    Operation = Fav5Operation.Add,
                    OrderKey = orderKey,
                    SIPUri = sipUri,
                    DisplayName = default(string),
                    IsPhoneNumber = default(bool),
                    Success = default(bool)
                };
                GadgetEventManager.Instance.OnFav5ChangedEvent(args);
            }
            else
            {
                ShowMessage("This contact already exists in your Fav 5.");
            }
        }

        void RemoveFav5(int orderKey, string displayName)
        {
            ShowMessage(null);

            GadgetConfigurationManager.RemoveFavorite5ByKey(orderKey);
            GadgetEventManager.Instance.OnFav5ChangedEvent(new Fav5ChangedEventArgs(Fav5Operation.Remove));

            ShowMessage(String.Format("Removed {0} from your Fav 5.", displayName));
        }

        void ModifyFav5(int orderKey, string displayName)
        {
            ShowMessage(null);

            GadgetConfigurationManager.ModifyFavorite5DisplayName(orderKey, displayName);
            GadgetEventManager.Instance.OnFav5ChangedEvent(new Fav5ChangedEventArgs(Fav5Operation.Modify));
        }

        void imgDelete_MouseDown(object sender, MouseButtonEventArgs e)
        {
            int slot = Convert.ToInt32(((Image)sender).Tag);

            FavoriteElementCollection currentFav5 = GadgetConfigurationManager.GetCurrentFav5List();
            FavoriteElement favElement = currentFav5.GetByOrderKey(slot);

            if (favElement != null)
            {
                RemoveFav5(slot, favElement.DisplayName);
            }
        }

        #endregion

        void ShowMessage(string message)
        {
            if (!String.IsNullOrEmpty(message))
            {
                gridMessage.Visibility = Visibility.Visible;
                tbMessage.Text = message;
            }
            else
            {
                tbMessage.Text = string.Empty;
                gridMessage.Visibility = Visibility.Collapsed;
            }
        }
    }
}